import re 

class EntityProcessor(object):
    """
    # Replace all &...; enities. 
    # &#number; replace automatically, for replacing &keyword; 
    # need dictionary at constructor. 
    >>> replacer = EntityProcessor({'amp': '&', 'apos': '`'})
    >>> print replacer('A&amp;B')
    A&B
    """
    _entity_re = re.compile('&([^;\s]+);')

    def __init__(self, entity_dict={}):
        self._entity_dict = entity_dict

    def __call__(self, s):
        return self._entity_re.sub(self._replace_entity, s)
        
    def _replace_entity(self, m):
        e = m.group(1)
        
        replacement = self._entity_dict.get(e)
        if replacement is not None:
            return replacement
        
        if e[0] == '#':
            try:
                num = int(e[1:])
            except:
                return u'&%s;' % e
            return unichr(num)

        return u'&%s;' % e


class OpenedTagsStat(object):
    """
    Structure for strorage opened tags statistics.
    
      OpenedTagsStat.tags - list of HtmlTag objects
      
      OpenedTagsStat.tagnames - string with lowercased opened names
      without attributes. like '<html><body><div><div>'
      
    """
    def __init__(self):
        self._tags = []
        self._refresh()
        
    @property    
    def tags(self):
        return self._tags

    @property    
    def tagnames(self):
        return self._tagnames

    @property    
    def last(self):
        return self._last
                    
    def drop_last(self, tag):
        for i in reversed(xrange(len(self._tags))):
            if self._tags[i].name == tag.name:
                del self._tags[i]
                self._refresh()
                break
            
    def append(self, tag):
        self._tags.append(tag)
        self._refresh()
            
    def _refresh(self):
        self._tagnames = ''.join('<%s>' % tag.name for tag in self._tags)
        self._last = self._tags and self._tags[-1] or None
        
